import { Injectable, EventEmitter } from '@angular/core';
import { Http } from "@angular/http";
import { Subject } from "rxjs/Subject";
import { SUMMARY_STATUS } from "summary-assistant";
export const SOCKET_ONLINE_STATUS = "SOCKET_ONLINE_STATUS";
import { BASEURL, SITEURL, WSURL, apiServer } from "shared";
let io = require("socket.io-client");

export interface TaskList {

};
export interface BROADCAST {
  event: any,
  symbol?: string
}

export interface ToListen {
  event: string;
  listener: (...any) => any;
}

export const BROADCAST_EVENT = {
  "RESET": -1,
  "ENTER_OCALL": 0,
  "ENTER_TRADE": 1
};

@Injectable()
export class SocketService {
  taskList = {};
  toListenArray: ToListen[] = [];
  broadcast: EventEmitter<BROADCAST> = new EventEmitter();
  socket;
  statusSet = {};
  onlineStateSub = new EventEmitter();
  socketSub = new Subject();

  constructor(private http: Http) {
    // setInterval(() => {
    //   console.debug("Socket: ", "Let's reload!!!");
    //   this.broadcast.next({
    //     event: BROADCAST_EVENT.ENTER_OCALL
    //   });
    // }, 5000);
    
    /*
    this.getSocketServer().subscribe(data => {
      let res = data.json();
      let linkUrl = res["url"];
      let path = res["path"];
      console.debug('res: ', res);
      this.socket = io.connect(linkUrl, { path });

      this.socketSub.next(res);
    }, err => {
      console.warn("socket 地址获取服务异常");
    });
    */

    this.socketSub.subscribe(res => {
      this.socket.on("connect", (data => {
        console.log("socket connect", data);
        this.onlineStateSub.next({
          type: SOCKET_ONLINE_STATUS,
          payload: true
        });
      }));
      this.socket.on("disconnect", (data => {
        console.log("socket dis-connect", data);
        this.onlineStateSub.next({
          type: SOCKET_ONLINE_STATUS,
          payload: false
        });

        //检查是否切换api服务器
        //if (this.socket.io && this.socket.io.opts && apiServer.checkReload(this.socket.io.opts.hostname)) {
        //  this.newConnection();
        //}
      }));
      this.socket.on("error", errObj => {
        console.error("Socket Error: ", errObj)
      });
      this.socket.on("detail", dynPanel => {

        // console.debug("Socket On Detail: ", dynPanel);
        // if (!dynPanel) return;
        /* adapt to v2 api
        Object
          .keys(dynPanel)
          .filter(symbol =>
            dynPanel[symbol]
            && dynPanel[symbol].status
            && this.statusSet[symbol] !== dynPanel[symbol].status
          )
          .forEach(symbol => {
        */
          let symbol = dynPanel.symbol;
          if (symbol && dynPanel.status) {
            if (!this.statusSet[symbol]) {
              this.statusSet[symbol] = dynPanel.status;
            } else if (this.statusSet[symbol] !== dynPanel.status) {
              console.debug("Socket Detail: a detail status changed: ", symbol);
              this.statusSet[symbol] = dynPanel.status;
              this.broadcast.next({
                event: BROADCAST_EVENT.RESET,
                symbol
              });
            }
          }
        // if (Object.keys(dynPanel).some(symbol => dynPanel[symbol].status)) {
        //   console.debug("Detail Socket: ", dynPanel);
        //   this.broadcast.next({
        //     event: BROADCAST_EVENT.RESET
        //   })
        // }
      });
      while (this.toListenArray.length && this.socket) {
        let toListen = this.toListenArray.shift();
        this.on(toListen.event, toListen.listener);
      }
      this.socket.on("reconnect", (attemptNumber) => {
        let backList = Object.assign({}, this.taskList);
        for (let i in backList) {
          console.debug("SUBJECT: ", JSON.parse(i));
          this.socket.emit("sub", JSON.parse(i), true);
        }
        this.onlineStateSub.next({
          type: SOCKET_ONLINE_STATUS,
          payload: true
        });

        console.debug("Socket Reconnet: ", attemptNumber, this.taskList);
        this.broadcast.next({
          event: BROADCAST_EVENT.RESET
        });
      });

      //this.socket.on("TimeSeries", data => console.debug("TimeSeries From Socket: ", data));
    });

    this.newConnection();
  }

  private newConnection() {
    try {
      this.socket = io.connect(WSURL, { path: "/sc/api-ws" });
      this.socketSub.next();    
    } catch(err) {
      console.error("socket switching", err)
    }
  }

  // 获取socket地址
  private getSocketServer() {
    return this.http.get(`${BASEURL}/ws/server`);
  }

  public off(event: string, fn) {
    this.socket ? this.socket.off(event, fn) : null;
  }

  public emit(e, data, isReload = false) {
    data['token'] = getToken()
    console.log("socket", e, data)
    data = JSON.stringify(data)
    if (isReload || this.updateSubList(e, data)) {
      return this.socket ? this.socket.emit(e, data, (body) => {
          //console.log("feedback",body)
      } ) : null;
    };
  }

  public on(e, fn) {
    //console.debug("Socket On: ", e, fn, this.socket);

    this.socket ? this.socket.on(e, fn) : this.toListenArray.push({
      event: e,
      listener: fn
    });
  }

  private updateSubList(e, data) {
    let key = JSON.stringify(data);
    switch (e) {
      case "sub":
        if (key in this.taskList) {
          this.taskList[key]++;
          return false;
        } else {
          this.taskList[key] = 1;
          return true;
        }
      case "unsub":
        if (key in this.taskList) {
          this.taskList[key]--;
          if (this.taskList[key] <= 0) {
            delete this.taskList[key];
            return true;
          } else {
            return false;
          }
        }
        return false;
    }
  }

  function getToken()
  {
    return window.sessionStorage.getItem("scToken");  
  }
}